package com.hancai.config;

import com.hancai.config.filter.TokenVerifyFilter;
import com.hancai.config.handler.MyAuthenticationFailureHandler;
import com.hancai.config.handler.MyAuthenticationSuccessHandler;
import com.hancai.config.handler.MyLogoutSuccessHandler;
import com.hancai.constant.Constants;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

/**
 * @author 涵菜
 * @version 1.0
 */
@Configuration
public class SecurityConfig {
    @Resource
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    @Resource
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;

    @Resource
    private TokenVerifyFilter tokenVerifyFilter;

    @Resource
    private MyLogoutSuccessHandler myLogoutSuccessHandler;

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity,CorsConfigurationSource configurationSource) throws Exception {
        return httpSecurity
                .formLogin((formLogin)->{
                    formLogin.loginProcessingUrl(Constants.LOGIN_URI)
                            .usernameParameter("loginAct")
                            .passwordParameter("loginPwd")
                            .successHandler(myAuthenticationSuccessHandler)
                            .failureHandler(myAuthenticationFailureHandler);
                })
                .authorizeHttpRequests((authorize)->{
                    //任何请求都需要登陆后才能访问
                    authorize.anyRequest().authenticated();
                })
                .csrf((csrf)->{
                    csrf.disable();//禁用跨站请求伪造
                })
                //支持跨域请求（协议，端口，域名任一个不同就是跨域）
                .cors((cors)->{
                    cors.configurationSource(configurationSource);
                })
                .sessionManagement((session)->{
                    //session创建策略
                    //无session状态，也就是禁用session
                    session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
                })
                //添加自定义的filter
                .addFilterBefore(tokenVerifyFilter, LogoutFilter.class)
                //退出登录-后端需要把redis中的登录token删掉
                .logout((logout)->{
                    //退出提交到该地址，该地址不需要我们写controller，是框架处理
                    logout.logoutUrl("/api/logout")
                            .logoutSuccessHandler(myLogoutSuccessHandler);
                })
                .build();
    }
    @Bean
    public CorsConfigurationSource configurationSource(){
        CorsConfiguration configuration=new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));//来源 http://localhost:8080
        configuration.setAllowedMethods(Arrays.asList("*"));//方式 POST,GET,PUT,DELETE
        configuration.setAllowedHeaders(Arrays.asList("*"));//请求头信息
        UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",configuration);
        return source;
    }
}
